package Youtube.actions;

import java.io.*;
import java.net.URL;
import java.util.*;

import LangDet.LangDetect;
import SentimentAnalysis.Sentiment;

import com.cybozu.labs.langdetect.LangDetectException;
import com.google.api.client.util.DateTime;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Activity;
import com.google.api.services.youtube.model.ActivityListResponse;
import com.google.api.services.youtube.model.Subscription;
import com.google.api.services.youtube.model.SubscriptionListResponse;
import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.Entry;
import com.google.gdata.data.Feed;
import com.google.gdata.data.TextContent;
import com.google.gdata.data.extensions.Comments;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.util.ServiceException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class YoutubeData {

	// Return a list of subscription of the specific level
	public Map<Subscription, Integer> subLevelSubscription(YouTube youtube, Map<Subscription, Integer> subscriptionMap,
			List<Subscription> subscriptionList,  int levelStartSubscription,  int levelDepthSubscription){		

		List<Subscription> subscriptionList2 = new ArrayList<Subscription>();
		YouTube.Subscriptions.List subscriptionRequest;
		//System.out.println(levelDepthSubscription);
		if(levelDepthSubscription!=1){
			for(Subscription s: subscriptionList){

				try {
					String chId = s.getSnippet().getResourceId().getChannelId();
					subscriptionRequest = youtube.subscriptions().list("snippet");
					subscriptionRequest.setChannelId(chId).setMaxResults(6L/levelStartSubscription);
					SubscriptionListResponse subscriptionResult = subscriptionRequest.execute();
					List<Subscription> subscriptionListTemp = subscriptionResult.getItems();
					//System.out.println(subscriptionListTemp);
					for(Subscription s2: subscriptionListTemp){
						subscriptionMap.put(s2, levelStartSubscription);
					}
					subscriptionList2.addAll(subscriptionListTemp);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();

				}		
			}
			int prevDepthLevel = levelDepthSubscription - 1;
			int nextStartLevel = levelStartSubscription + 1;
			//System.out.println(levelDepthSubscription);
			subLevelSubscription(youtube, subscriptionMap, subscriptionList2, nextStartLevel, prevDepthLevel);
		}
		return subscriptionMap;
	}

	// Sort videos
	public Map<String, Double> sortVideo4Priority(Map<String, Double> activity) {
		ActivitiesComparator pc = new ActivitiesComparator(activity);
		TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(pc);

		sorted_map.putAll(activity);

		return sorted_map;
	}

	// Filter the activity list where a "friend" give a like to a video
	public Map<String, Double> getVideoLike(List<Activity> activityList, int level) {
		Map<String, Double> videos = new HashMap<String, Double>();
		for (Activity a : activityList){
			//System.out.println(a.getSnippet());
			if (a.getSnippet().getType().equals("like")) {
				String url = a.getSnippet().getThumbnails().getDefault().getUrl();
				String[] urlSplit = url.split("/vi/");
				String videoId = urlSplit[1].split("/")[0];
				videos.put(videoId, (activityList.size()/50.0)/level);
			}
		}
		return videos;
	}


	// Returns a map with the video id and the amount of activity in the last three months of a subscription
	public Map<String, Double> getVideo2Activity(Map<Subscription, Integer> subscriptionMap, YouTube youtube) throws IOException {
		Map<String, Double> video2ChannelActivity = new HashMap<String, Double>();

		/* 
		 * Get the activities number of the last three months for each subscription 
		 */
		YouTube.Activities.List activityRequest = youtube.activities().list("snippet");
		DateTime before = new DateTime(new Date());
		DateTime after = new DateTime (before.getValue()-8035200000L);
		activityRequest.setPublishedAfter(after).setPublishedBefore(before);

		for (Subscription s : subscriptionMap.keySet()){
			//System.out.println(s.getSnippet());

			String chId = s.getSnippet().getResourceId().getChannelId();
			//System.out.println(chId);

			activityRequest.setChannelId(chId).setMaxResults(50L);
			ActivityListResponse activityResult = activityRequest.execute();
			List<Activity> activityList = activityResult.getItems();
			video2ChannelActivity.putAll(getVideoLike(activityList, subscriptionMap.get(s)));
		}

		return video2ChannelActivity;
	}

	// Returns the sentiment analysis of video
	public double videoSentiment(String idVideo, YouTubeService service, LangDetect lg) throws LangDetectException {
		Sentiment sent = new Sentiment();
		ArrayList<String> comNoFiltered = new ArrayList<String>();
		ArrayList<String> comFiltered = new ArrayList<String>();
		double sentiment = -2;
		int count = 0;
		double totSent = 0;
		String videoEntryUrl = "http://gdata.youtube.com/feeds/api/videos/"+idVideo;
		try {
			VideoEntry videoEntry = service.getEntry(new URL(videoEntryUrl), VideoEntry.class);
			Comments comments = videoEntry.getComments();
			if (comments != null && comments.getFeedLink() != null) {
				Feed feed = service.getFeed(new URL(comments.getFeedLink().getHref()), Feed.class);
				for (Entry e : feed.getEntries()) {
					TextContent content = (TextContent) e.getContent();
					String comment = content.getContent().getPlainText();
					comNoFiltered.add(comment);

				}
				comFiltered = lg.filterComments(comNoFiltered);
				for(String text: comFiltered){
					if (sent.sentiment(text)!=-2){
						totSent += sent.sentiment(text);
						count++;
					}
				}
				if (count!=0){
					sentiment = totSent/count;
				}
			}
		} catch (IOException | ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return sentiment;
	}

	// Get the ranking of videos 
	public List<String> videoList(Map<String, Double> video2Activity, Map<String, Double> video2Sentiment) {
		List<String> rank = new ArrayList<String>();
		List<String> rankLink = new ArrayList<String>();
		Map<String, Double> rankMax = new HashMap<String, Double>();
		Map<String, Double> rankMin = new HashMap<String, Double>();
		Map<String, Double> rank0 = new HashMap<String, Double>();
		for(String id: video2Sentiment.keySet()){
			double s = video2Sentiment.get(id);
			double p = video2Activity.get(id);
			double r = 0;
			if (s>0 && p!=0){
				r= p*s;
				rankMax.put(id, r);
			}else if (s<0 && p!=0){
				r= -(p*s);
				rankMin.put(id, r); 
			}else{
				rank0.put(id, s);
			}
		}
		rankMax = sortVideo4Priority(rankMax);
		rankMin = sortVideo4Priority(rankMin);
		rank0 = sortVideo4Priority(rank0);
		
		Map<String, Double> rankFinal = new HashMap<String, Double>();
		rankFinal.putAll(rankMax);
		rankFinal.putAll(rankMin);
		rankFinal.putAll(rank0);
		
		rank.addAll(rankMax.keySet());
		rank.addAll(rank0.keySet());
		rank.addAll(rankMin.keySet());
		
		
		
		for (String s : rank) {
			//rankLink.add("https://www.youtube.com/watch?v="+s);
			rankLink.add("https://www.youtube.com/watch?v="+s + "    weight: " + rankFinal.get(s));
		}
		return rankLink;
	}

	public List<String> getMyVideoLike(YouTube youtube) {
		List<String> videos =  new ArrayList<String>();
		try {
			YouTube.Activities.List activityRequest = youtube.activities().list("snippet");
			activityRequest.setMine(true);
			ActivityListResponse activityResult = activityRequest.execute();
			List<Activity> activityList = activityResult.getItems();
			videos.addAll(getVideoLike(activityList,1).keySet());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return videos;
	}

	public Map<String, Double> filterVideoLike(Map<String, Double> video2Activity, List<String> myVideosLike) {
		
		Map<String, Double> finalMapVideo = new HashMap<String, Double>();
		for(String id: video2Activity.keySet()){
			if(!myVideosLike.contains(id)){
				finalMapVideo.put(id, video2Activity.get(id));
			}
		}
		return finalMapVideo;
	}



}